using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using Microsoft.VisualBasic;
using Microsoft.Win32;
using System.Text;
using System.Runtime.InteropServices.ComTypes;

namespace Tsanie.ShellExtension {

    /// <summary>
    /// Base class for Icon handlers
    /// </summary>
    public abstract class IconHandlerBase : IExtractIconA, IExtractIconW, IPersistFile {

        #region - Privated Fields -

        private string m_FileName;

        #endregion

        #region - Constructors -

        protected IconHandlerBase() : base() { }

        #endregion

        #region - public Properties -

        /// <summary>
        /// Gets the filename of the file for which the icon will
        /// be generated
        /// </summary>
        public string Filename { get { return m_FileName; } }

        #endregion

        #region - Public Methods -

        /// <summary>
        /// Notifies that an icon file location is required
        /// </summary>
        /// <param name="IconFile">
        /// Receives the file that contains the icon.</param>
        /// <param name="IconIndex">
        /// Receives the index of the icon in the file
        /// pointed to by IconFile.</param>
        /// <param name="Flags">Specifies the type of the icon.</param>
        /// <returns></returns>
        public abstract IconHandlerReturnFlags OnGetIconLocation(
            out string iconFile,
            ref int iconIndex,
            IconHandlerFlags flags);
        /// <summary>
        /// 
        /// </summary>
        /// <param name="IconFile">Specifies the icon location.</param>
        /// <param name="IconIndex">The index of the icon in the file pointed to by IconFile</param>
        /// <param name="LargeIcon">Receives a handle to the large icon.</param>
        /// <param name="SmallIcon">Receives a handle to the small icon.</param>
        /// <param name="LargeSize">The size of the large icon.</param>
        /// <param name="SmallSize">The size of the small icon.</param>
        public abstract void OnExtractIcon(
            string iconFile,
            int iconIndex,
            ref IntPtr largeIcon,
            ref IntPtr smallIcon,
            int largeSize,
            int smallSize);

        #endregion

        #region - IPersistFile Methods -

        void IPersistFile.GetClassID(out Guid pClassID) { pClassID = Guid.Empty; }
        void IPersistFile.GetCurFile(out string ppszFileName) { ppszFileName = null; }
        int IPersistFile.IsDirty() { return default(int); }
        void IPersistFile.Load(string pszFileName, int dwMode) { m_FileName = pszFileName; }
        void IPersistFile.Save(string pszFileName, bool fRemember) { }
        void IPersistFile.SaveCompleted(string pszFileName) { }

        #endregion

        #region - IExtractIcon Methods -

        public void Extract(
            string pszFile,
            int nIconIndex,
            ref IntPtr phiconLarge,
            ref IntPtr phiconSmall,
            int nIconSize
        ) {
            int LargeSize, SmallSize;
            LargeSize = nIconSize & 0xFFFF;
            SmallSize = nIconSize / 0x10000;
            this.OnExtractIcon(pszFile, nIconIndex, ref phiconLarge, ref phiconSmall, LargeSize, SmallSize);
        }

        public IconHandlerReturnFlags GetIconLocation(
            IconHandlerFlags uFlags,
            StringBuilder szIconFile,
            int cchMax,
            ref int piIndex
        ) {
            string IconFile;
            IconHandlerReturnFlags Flags;
            try {
                Flags = this.OnGetIconLocation(out IconFile, ref piIndex, uFlags);
                if (IconFile == null || IconFile.Length == 0) {
                    // If not filename is returned add
                    // the NotFilename flag to the
                    // return value
                    Flags = Flags | IconHandlerReturnFlags.NotFilename;
                } else {
                    szIconFile = new StringBuilder(IconFile);
                }
            } catch {
                Flags = IconHandlerReturnFlags.DontCache | IconHandlerReturnFlags.NotFilename | IconHandlerReturnFlags.PerInstance;
            }
            return Flags;
        }

        #endregion

        #region - COM Registration -

        [ComRegisterFunction()]
        [EditorBrowsable(EditorBrowsableState.Never)]
        private static void ComReg(Type t) {
            // Register the extension
            Common.RegisterExtension(t, "IconHandler");

        }
        [ComUnregisterFunction()]
        [EditorBrowsable(EditorBrowsableState.Never)]
        private static void ComUnreg(Type t) {
            // Unregister the extension
            Common.UnregisterExtension(t, "IconHandler");

        }

        #endregion

    }

}
